import poser, os, sys, string, re, time

def isCompatiblePoser():
	try:
		poser.Scene().CurrentFireFlyOptions().Manual()
		return 1
	except:
		print "GlowWorm requires that Poser 6 Service Release 2, or higher, be installed.\n\nPoser updates may be downloaded from http://www.e-frontier.com\n\nPlease install any necessary updates before continuing."
		return 0

os.chdir( os.path.dirname(poser.AppLocation()) )

sys.path.append( os.path.join("Runtime","Python","PoseWorks","GlowWorm","Data"))

import gwrRender, gwrPass, gwrJob, gwrParse
from gwrXml import *
from gwrVars import *

DataDir = os.path.join("Runtime","Python","PoseWorks","GlowWorm","Data")

settingsFile = os.path.join(DataDir,"settings.gwr")

defaultSettingsDict = {
			"doLog":1,
			"showLog":1,
			"warnIf":1,
			"runSims":1,
			"rp":os.path.join("Runtime","Python","PoseWorks","GlowWorm","RenderPasses"),
			"addFile":os.path.dirname(poser.AppLocation()),
			"saveFile":os.path.dirname(poser.AppLocation()),
			"fx6":os.path.join("Runtime","Python","PoseWorks","GlowWorm","FX"),
			"aoSamples":3.0,
			"aoMaxDist":7.74,
			"aoRayBias":0.2064,
			"aoStrength":1.0,
			"closeOnFinish":0,
			"shutdownOnFinish":0,
			}

def writeSettings(*args, **kwds):
	d = getSettings()
	d.update(kwds)
	writeSettingsToFile(d)

def writeSettingsToFile(d):
	fi = open(settingsFile, 'w')
	for k,v in d.items():
		if type(v) != type("string"):
			v = repr(v)
		fi.write("%s %s\n" % (k,v) )
	fi.close()

def getSettings():
	d = defaultSettingsDict
	if os.path.exists(settingsFile):
		fi = open(settingsFile, 'r')
		rl = fi.readlines()
		fi.close()
		for line in rl:
			line = line.strip()
			if not line:
				continue
			else:
				kv = line.split()
				if len( line.split() ) < 2:
					continue
				elif re.search("[a-zA-z]",kv[1]):
					v = string.join(kv[1:])
				elif len(kv[1:]) > 1:
					v = tuple( filter(float, kv[1:]) )
				else:
					v = float(kv[1])
				d[ kv[0] ] = v
		return d
	else:
		writeSettingsToFile(d)
		return getSettings()

def setPref(prefCode, prefVal):
	d = getSettings()
	d[prefCode] = prefVal
	writeSettingsToFile(d)

def getPref(prefCode):
	return getSettings()[prefCode]

def doClose():
	if getPref(PREF_CLOSE):
		if GLOWWORM_PLATFORM != 'nt':
			pass
		else:
			os._exit(1)

def doShutdown():
	if getPref(PREF_SHUTDOWN) and GLOWWORM_PLATFORM == "nt":
        	poser.CloseDocument(1)
		os.system("shutdown -s -f")

def askRenderAll():
	dlg = PzrDialog(width=320, height=220)
	vm_win = [getPref(PREF_CLOSE), getPref(PREF_SHUTDOWN)]
	vm_mac = []
	if GLOWWORM_PLATFORM == "mac":
		vm = vm_mac
	else:
		vm = vm_win
	opts = PzrCheckPane(valueMap=vm)
	if GLOWWORM_PLATFORM == "nt":
		opts.AddCheckbutton( TEXT_CLOSE )
		opts.AddCheckbutton( TEXT_SHUTDOWN )
	dlg.add( PzrMessage( TEXT_ASKRENDER, text=PzrText(size=16)), 84, 70)
	dlg.add( opts, 40, 112 )
	dlg.add( PzrButtonWidget( TEXT_YES, command=7001, text=PzrText(size=14)), dlg.width-70, dlg.height-26)
	dlg.add( PzrButtonWidget( TEXT_NO, command=7002, text=PzrText(size=14)), dlg.width-125, dlg.height-26)
	if dlg.Show():
		results = opts.get()
		if TEXT_CLOSE in results:
			setPref(PREF_CLOSE, 1)
		else:
			setPref(PREF_CLOSE, 0)
		if TEXT_SHUTDOWN in results:
			setPref(PREF_SHUTDOWN, 1)
		else:
			setPref(PREF_SHUTDOWN, 0)
		return 1
	else:
		return 0

fontColor = PzrColor(69,68,50)
#PzrColor(150,146,128)
#PzrColor(172,164,145)
versFont = PzrText(font=1, color=fontColor, size=13)
liteFont = PzrText(font=1, color=fontColor, size=13, italic=1)
jobFont = PzrText(font=1, color=fontColor, size=12)
titleFont = PzrText(font=1, color=fontColor, size=16)
fancyFont = PzrText(font=1, color=fontColor, size=13)

class renderLog:
	def __init__(self):
		self.file = VAR_LOGFILE
		fi = open(self.file,'w')
		fi.write("GlowWorm Render Log")
		fi.close()
		self.last = None
		self.add("Log created")
	def pad(self, n, slots=2):
		n = repr(n)
		while len(n) < slots: n = "0" + n
		return n
	def getTime(self):
		return time.strftime("%m/%d/%Y %H:%M:%S", time.localtime(time.time()))
	def add(self, text):
		if text != self.last:
			self.write(text)
			self.last = text
	def write(self, text):
		fi = open(VAR_LOGFILE,'a')
		fi.write( "\n%s | %s" % (self.getTime(), text))
		fi.close()

def zPad(number, width=4):
	if type(number) != type("string"):
		number = repr(number)
	decimal = string.find(number, ".")
	if decimal == -1 or not decimal:
		number = number + "." + "0" * width
	else:
		post = number[number.index(".")+1:]
		if len(post) > width:
			number = number[:width]
		else:
			for i in range( width - len(post) ):
				number = number + "0"
	return number

class Float6Button(PzrFloatButton):
	def FormatText(self, text):
		return zPad(text,width=6)
	def FormatValue(self, value):
		setPref(self.widgetName, value)
		return float(value)

class FileNameButton(PzrFileButton):
	def FormatText(self, text):
		return os.path.basename(text)

class colorSwatch:
	def __init__(self, widgetName, command=10002, pictRes=13010, color=(1,0,0)):
		self.widgetName = widgetName
		self.btn = PzrWidget(widgetName, command=command, groupID=23, pictRes=pictRes, hiliteRes=pictRes + 1, behaviorProcID=3, preliteAction=1, bb=PzrRect(left=0,top=0,right=40,bottom=40), rect=PzrRect(left=0,top=0,right=40,bottom=40), useRectClick=1, pin=PzrRect(id=1,left=1,top=3,right=1,bottom=3), color=-1, fadeMax=0)
		self.set( color[0], color[1], color[2] )
	def set(self, r, g, b):
		self.r, self.g, self.b = r, g, b
	def get(self):
		return (self.r, self.g, self.b)
	def place(self, x, y):
		return self.btn.place(x, y)
	def SetDialog(self, dialog):
		pass

swatchColors = [("swBlack", 13040, (0,0,0)),
		("swRed", 13010, (1,0,0)),
		("swGreen", 13020, (0,1,0)),
		("swBlue", 13030, (0,0,1)),
		("swWhite", 13080, (1,1,1)),
		("swYellow", 13050, (1,1,0)),
		("swPurple", 13060, (1,0,1)),
		("swTeal", 13070, (0,1,1))]

swatches3x3 = [	("swRed", 13010, (1,0,0)),
		("swGreen", 13020, (0,1,0)),
		("swBlue", 13030, (0,0,1)),
		("swYellow", 13050, (1,1,0)),
		("swPurple", 13060, (1,0,1)),
		("swTeal", 13070, (0,1,1)),
		("swBlack", 13040, (0,0,0)),
		("swWhite", 13080, (1,1,1))]

class SwatchPane:
	def __init__(self, initCommand=10002, itemsPerRow=4, default=0, colors=swatchColors):
		self.color = (0,0,0)
		self.itemsPerRow = itemsPerRow
		self.swatches = []
		curCommand = initCommand
		for wN, pR, col in colors:
			self.swatches.append( colorSwatch(wN, pictRes=pR, command=curCommand, color=col) )
			curCommand = curCommand + 1
		self.var = self.swatches[default].widgetName
	def set(self, dialog, value):
		self.var = value
		for button in self.swatches:
			dialog.SetButtonValue(name=button.widgetName, value=0)
			if (button.get() == value) or (button.widgetName == value):
				self.color = button.get()
				dialog.SetButtonValue(name=button.widgetName, value=1)
	def SetValues(self, dialog):
		for button in self.swatches:
			dialog.AddButtonCallback(name=button.widgetName, callback=lambda v, s=self, d=dialog, n=button.widgetName: s.set(d,n))
			dialog.SetButtonValue(name=button.widgetName, value=0)
		dialog.SetButtonValue(self.swatches[0].widgetName, value=1)
	def SetDialog(self, dialog):
		self.SetValues(dialog)
		self.set(dialog, self.var)
	def place(self, x, y):
		self.xml = ""
		for i in range(8):
			self.xml = self.xml + "\n" + self.swatches[i].place(x + i%self.itemsPerRow*46, y+46*int(i/self.itemsPerRow))
		return self.xml
	def get(self):
		return self.color

class colorPicker:
	def __init__(self, default=0):
		self.dlg = PzrDialog(width=300,height=240,palettes="./runtime/Python/PoseWorks/GlowWorm/Data/13000.psd")
		self.color = (0,0,0)
		self.var = default
		self.swatches = SwatchPane(default=self.var)
		self.dlg.add( PzrMessage( TEXT_KNOCKOUT, text=PzrText(size=18)), 24, 40)
		self.dlg.add( PzrMessage( INFO_KNOCKOUT, text=PzrText(size=14,italic=1)), 24, 64)
		self.dlg.add(self.swatches, 62, 96)
		self.dlg.add( PzrCancelButton(), 164, 214)
		self.dlg.add( PzrOkButton(), 230, 214)
	def get(self):
		return self.swatches.get()
	def Show(self):
		return self.dlg.Show()

class PassNameButton(PzrValueButton):
	null = None
	def AskValue(self, event=None):
		newValue = AskText(message="")
		if newValue:
			self.set(newValue, newValue)
		else:
			return self.null
	def FormatText(self, text):
		return re.sub("""[^a-zA-Z0-9_\-]""", '_', text)

class KnockOutButton(PzrValueButton):
	defaultText = "Black"
	defaultValue = (0,0,0)
	def AskValue(self):
		color = self.value
		id = [[[0,3],[2,7]],[[1,6],[5,4]]][color[0]][color[1]][color[2]]
		cp = colorPicker(default=id)
		if cp.Show():
			return cp.get()
		else:
			return self.null
	def FormatText(self, color):
		if type(color) == type(""): return color
		return [[[TEXT_BLACK,TEXT_BLUE],[TEXT_GREEN,TEXT_TEAL]],[[TEXT_RED,TEXT_PURPLE],[TEXT_YELLOW,TEXT_WHITE]]][color[0]][color[1]][color[2]]

class SelectPRPButton(PzrMenuButton):
	defaultText = TEXT_LOAD
	defaultValue = os.path.join("Runtime","prefs","RenderPresets")
	defaultMessage = TEXT_SELPRESET
	defaultExtension = "prp"
	def GetOptions(self):
		prps = []
		for prp in os.listdir( self.default ):
			prps.append( os.path.splitext(prp)[0] )
		return prps
	def FormatText(self, text):
		return os.path.splitext(os.path.basename(text))[0]
	def FormatValue(self, value):
		return os.path.join(self.default, value + "." + self.defaultExtension)

class SelectPZSButton(SelectPRPButton):
	defaultText = TEXT_LOAD
	defaultValue = os.path.join("Runtime","prefs","SketchPresets")
	defaultMessage = TEXT_SELPRESET
	defaultExtension = "pzs"

class SelectFX6Button(PzrValueButton):
	defaultText = TEXT_NONE
	defaultValue = None
	defaultMessage = TEXT_FX6
	defaultExtensions = (".fx6",".FX6")
	def GetDir(self, value):
		if not value: return getPref(PREF_FX6)
		else: return os.path.dirname(value)
	def AskValue(self):
		return AskOpen(extensions=self.defaultExtensions, dir=getPref(PREF_FX6), title=self.message)
	def FormatText(self, text):
		if text:
			setPref(PREF_FX6, self.GetDir(text))
			newText = os.path.basename(text)
			if len(newText) > 14: newText=newText[:13]
			return newText
		else: return "None"

class renderPassMaker:
	headline = titleFont
	biline = PzrText(font=1, color=fontColor, size=14, italic=1)
	types = [TEXT_LIGHTING, TEXT_DIFFUSE_COLOR, TEXT_SHADOWS_ONLY, TEXT_AMBIENT_OCCL, TEXT_DEPTH_MASK, TEXT_HAIR_ONLY, TEXT_PARTICLES_ONLY, TEXT_SELECT_ATTRIBS_ONLY]
	ids = [CODE_LIGHTING, CODE_DIFFUSE_COLOR, CODE_SHADOWS_ONLY, CODE_AMBIENT_OCCL, CODE_DEPTH_MASK, CODE_HAIR_ONLY, CODE_PARTICLES_ONLY, CODE_SELECT_ATTRIBS_ONLY]
	def typeClick(self, v):
		value =  self.ids[self.types.index(v)]
		self.passNameBtn.set(value, value)
	def __init__(self, pName="CustomPass", pType=5):
		self.passType = 0
		dW, dH = 370, 508
		self.dlg = PzrDialog(width=dW, height=dH, palettes="./runtime/Python/PoseWorks/GlowWorm/Data/13000.psd")

		self.dlg.add( PzrMessage(TEXT_RENDERPASS_OPTIONS, text=self.headline), 24, 6)

		y = 40

		self.typeChooser = PzrRadioPane(groupID=100, initCommand=10101)
		self.typeChooser.setOnClick(self.typeClick)
		for radName in self.types:
			self.typeChooser.AddRadiobutton(radName)
			if radName == TEXT_LIGHTING:
				self.typeChooser.AddPaddingAfter(radName, 0, 36)
		self.typeChooser.var = TEXT_SELECT_ATTRIBS_ONLY
		self.dlg.add( self.typeChooser, 24, y )

		self.chkPassPerLight = PzrCheck(TEXT_PASS_PER_LIGHT, command=10150)
		self.dlg.add(self.chkPassPerLight, 48, y+16)

		self.chkShadows = PzrCheck(TEXT_CAST_SHADOWS, command=10151)
		self.dlg.add(self.chkShadows, 48, y+34)

		self.attribChooser = PzrCheckPane(groupID=200, initCommand=10201)
		self.attribs = [ TEXT_ATTRIB_DIFFUSE, TEXT_ATTRIB_SPECULAR, TEXT_ATTRIB_AMBIENT, TEXT_ATTRIB_TRANSLUCENCE, TEXT_ATTRIB_REFLECTION, TEXT_ATTRIB_REFRACTION, TEXT_ATTRIB_ALTDIFFUSE, TEXT_ATTRIB_ALTSPECULAR, TEXT_ATTRIB_SHADOWS, TEXT_ATTRIB_HAIR, TEXT_ATTRIB_PARTICLES ]
		for chkName in self.attribs:
			self.attribChooser.AddCheckbutton(chkName)
		self.dlg.add( self.attribChooser, 48, y + 180 + 18)

		x, y = 214, 132

		self.dlg.add( PzrMessage(TEXT_FILE_SUFFIX, text=self.biline), x, 38)
		self.passNameBtn = PassNameButton("passName", command=10301)
		self.passNameBtn.set(pName, pName)
		self.dlg.add( self.passNameBtn, x, 56)

		self.dlg.add( PzrMessage(TEXT_KNOCKOUT, text=self.biline), x, 90)
		self.knockOutColor = SwatchPane(initCommand=10500, itemsPerRow=3, default=6, colors=swatches3x3)
		self.dlg.add( self.knockOutColor, x, 108)
		#self.knockBtn = KnockOutButton("knockCol", command=10051)
		#self.dlg.add( self.knockBtn, x, 104)

		y = y + 118

		self.dlg.add( PzrMessage(TEXT_PRESETS, text=self.biline), x, y)
		y = y + 18

		quickPasses = [	PzrButton(TEXT_PASS_NORMAL, command=10001, callback=self.SetNormalRender),
				PzrButton(TEXT_PASS_BEAUTY, command=10013, callback=self.SetBeautyPass),
				PzrButton(TEXT_PASS_SHADING, command=10012, callback=self.SetLightingPass),
				PzrButton(TEXT_PASS_COLOR, command=10003, callback=self.SetDiffusePass),
				PzrButton(TEXT_PASS_SPECULAR, command=10004, callback=self.SetSpecularPass),
				PzrButton(TEXT_PASS_GLOW, command=10005, callback=self.SetAmbientPass)
				 ]
		for btn in quickPasses:
			self.dlg.add( btn, x, y )
			y = y + 25

		self.dlg.add( PzrMessage(TEXT_PARTIAL_SHADER, text=self.biline), x, 420)
		self.fx6Button = SelectFX6Button("LoadFX6File")
		self.dlg.add( self.fx6Button, x, 438)

		self.dlg.add( PzrOkButton(), dW-70, dH-26)
		self.dlg.add( PzrCancelButton(), dW-140, dH-26)

		self.dlg.add( PzrImageButton("saveBtn", callback=self.AskSave, command=10600, pictRes=13502, hiliteRes=13503, width=19, height=19), dW-36, 4)
		self.dlg.add( PzrImageButton("loadBtn", callback=self.AskLoad, command=10601, pictRes=13500, hiliteRes=13501, width=23, height=19), dW-66, 4)
	def get(self):
		id = self.passNameBtn.get()
		fx6 = self.fx6Button.get()
		koCol = self.knockOutColor.get()
		koCol = gwrPass.color(koCol[0],koCol[1],koCol[2])
		Kd, Ks, Ka, Ku, Kr, Kf, Kad, Kas, shadows, showHair, showParticles, passPerObject = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
		passPerLight, shadingPassShadows = self.chkPassPerLight.get(), self.chkShadows.get()
		attrList = [0,0,0,0,0,0,0,0]
		attrList[self.types.index(self.typeChooser.get())] = 1
		li, di, so, ao, zb, ho, po, nr = attrList
		if ao:
			d = getSettings()
			md = float(d["aoMaxDist"])
			samp = float(d["aoSamples"])
			rb = float(d["aoRayBias"])
			str = float(d["aoStrength"])
			aoOpts = aoOptions(maxDist=md, samples=samp, rayBias=rb, strength=str).Show()
		else:
			aoOpts = gwrPass.occlusionOptions()
		if not so and not ao:
			attribs = self.attribChooser.get()
			Kd = TEXT_ATTRIB_DIFFUSE in attribs
			Ks = TEXT_ATTRIB_SPECULAR in attribs
			Ka = TEXT_ATTRIB_AMBIENT in attribs
			Ku = TEXT_ATTRIB_TRANSLUCENCE in attribs
			Kr = TEXT_ATTRIB_REFLECTION in attribs
			Kf = TEXT_ATTRIB_REFRACTION in attribs
			Kad = TEXT_ATTRIB_ALTDIFFUSE in attribs
			Kas = TEXT_ATTRIB_ALTSPECULAR in attribs
			shadows = TEXT_ATTRIB_SHADOWS in attribs
			showHair = TEXT_ATTRIB_HAIR in attribs
			showParticles = TEXT_ATTRIB_PARTICLES in attribs
			passPerObject = TEXT_PASS_PER_OBJECT in attribs
		return gwrPass.renderPass(id=id, altdiffuse=Kad, altspecular=Kas, koColor=koCol, fx6=fx6, passPerObject=passPerObject, passPerLight=passPerLight, shadingPassShadows=shadingPassShadows, lightingOnly=li, diffuseOnly=di, showHair=showHair, showParticles=showParticles, hairOnly=ho, zbuffer=zb, particlesOnly=po, shadows=shadows, diffuse=Kd, specular=Ks, ambient=Ka, translucence=Ku, reflection=Kr, refraction=Kf, occlusion=ao, shadowOnly=so, aoOptions=aoOpts)
	def AskSave(self, event=None):
		outFile = AskSaveAs(extensions=(".gw6"), dir=getPref(PREF_RP))
		if outFile:
			self.Save(outFile)
			setPref(PREF_RP, os.path.dirname(outFile))
	def AskLoad(self, event=None):
		inFile = AskOpen(extensions=(".gw6"), dir=getPref(PREF_RP))
		if inFile:
			self.Load(inFile)
			setPref(PREF_RP, os.path.dirname(inFile))
	def Save(self, filepath):
		rp = self.get()
		fi = open(filepath, 'w')
		fi.write( gwrParse.writeRenderPass(rp)[2:] )
		fi.close()
	def Load(self, filepath):
		fi = open(filepath)
		input = fi.read()
		fi.close()
		rp = gwrParse.loadRenderPass(input.splitlines())
		self.set(rp)
	def set(self, rp):
		if rp.shadowOnly: self.SetType( TEXT_SHADOWS_ONLY )
		elif rp.diffuseOnly: self.SetType( TEXT_DIFFUSE_COLOR )
		elif rp.lighting: self.SetType( TEXT_LIGHTING )
		elif rp.hair: self.SetType( TEXT_HAIR_ONLY )
		elif rp.particles: self.SetType( TEXT_PARTICLES_ONLY )
		elif rp.zbuffer: self.SetType( TEXT_DEPTH_MASK )
		elif rp.occlusion: self.SetType( TEXT_AMBIENT_OCCL )
		else: self.SetType( TEXT_SELECT_ATTRIBS_ONLY )
		self.SelectAttributes(0)
		for k, v in vars(rp).items():
			if TRANSLATOR_ATTRIB.has_key(k):
				self.SetAttribute( TRANSLATOR_ATTRIB[k], v)
		if rp.passPerLight: self.chkPassPerLight.select(self.dlg)
		if rp.shadingPassShadows: self.chkShadows.select(self.dlg)
		self.SetPassName(rp.id)
		self.SetKOColor(rp.koColor.getTuple())
		self.SetPartialShader(rp.fx6)
	def SetPassName(self, name="CustomPass"):
		self.passNameBtn.set(name,name)
	def SetKOColor(self, color=(0,0,0)):
		self.knockOutColor.set(self.dlg, color)
	def SetPartialShader(self, fx6=None):
		if fx6:
			self.fx6Button.ChangeValue(fx6)
			self.fx6Button.ChangeText(fx6)
	def SelectAttributes(self, onoff=1, notLite=1):
		for n in self.attribs:
			self.SetAttribute(n, onoff)
		if notLite:
			self.chkShadows.deselect(self.dlg)
			self.chkPassPerLight.deselect(self.dlg)
		elif onoff:
			self.chkShadows.select(self.dlg)
	def SetShadowPass(self, event=None):
		self.SetType( TEXT_SHADOWS_ONLY )
		self.SelectAttributes(0)
		self.SetPassName("shd")
	def SetLightingPass(self, event=None):
		self.SetType( TEXT_LIGHTING )
		self.SelectAttributes(0)
		self.chkShadows.select(self.dlg)
		self.SetPassName("lite")
	def SetBeautyPass(self, event=None):
		self.SetType( TEXT_SELECT_ATTRIBS_ONLY )
		self.SelectAttributes(0)
		self.SetAttribute( TEXT_ATTRIB_DIFFUSE, 1)
		self.SetAttribute( TEXT_ATTRIB_HAIR, 1)
		self.SetPassName("beau")
	def SetAOPass(self, event=None):
		self.SetType( TEXT_AMBIENT_OCCL )
		self.SelectAttributes(0)
		self.SetPassName("ao")
	def SetZbPass(self, event=None):
		self.SetType( TEXT_DEPTH_MASK )
		self.SelectAttributes(0)
		self.SetPassName("zb")
	def SetHairPass(self, event=None):
		self.SetType( TEXT_HAIR_ONLY )
		self.SelectAttributes(0)
		self.SetPassName("fur")
	def SetFxPass(self, event=None):
		self.SetType( TEXT_PARTICLES_ONLY )
		self.SelectAttributes(0)
		self.SetPassName("fx")
	def SetNormalRender(self, event=None):
		self.SetType( TEXT_SELECT_ATTRIBS_ONLY )
		self.SelectAttributes(1,notLite=1)
		self.SetPassName("ff")
	def SetPerObjectRender(self, event=None):
		self.SetNormalRender()
		self.SetAttribute( TEXT_ATTRIB_PASS_PER_OBJ, 1 )
	def SetDiffusePass(self, event=None):
		self.SetType( TEXT_DIFFUSE_COLOR )
		self.SelectAttributes(0)
		self.SetPassName("dif")
	def SetSpecularPass(self, event=None):
		self.SetType( TEXT_SELECT_ATTRIBS_ONLY )
		self.SelectAttributes(0)
		self.SetAttribute( TEXT_ATTRIB_SPECULAR, 1)
		self.SetAttribute( TEXT_ATTRIB_HAIR, 1)
		self.SetPassName("spec")
	def SetAmbientPass(self, event=None):
		self.SetType( TEXT_SELECT_ATTRIBS_ONLY )
		self.SelectAttributes(0)
		self.SetAttribute( TEXT_ATTRIB_AMBIENT, 1)
		self.SetAttribute( TEXT_ATTRIB_HAIR, 1)
		self.SetPassName("glow")
	def SetReflectionPass(self, event=None):
		self.SetType( TEXT_SELECT_ATTRIBS_ONLY )
		self.SelectAttributes(0)
		self.SetAttribute( TEXT_ATTRIB_REFLECTION, 1)
		self.SetAttribute( TEXT_ATTRIB_HAIR, 1)
		self.SetPassName("refl")
	def SetRefractionPass(self, event=None):
		self.SetType( TEXT_SELECT_ATTRIBS_ONLY )
		self.SelectAttributes(0)
		self.SetAttribute( TEXT_ATTRIB_REFRACTION, 1)
		self.SetAttribute( TEXT_ATTRIB_HAIR, 1)
		self.SetPassName("refr")
	def SetType(self, id):
		self.typeChooser.set(id)
	def SetAttribute(self, attribId, onoff):
		if onoff: self.attribChooser.select(self.dlg, attribId)
		else: self.attribChooser.deselect(self.dlg, attribId)
	def Show(self):
		return self.dlg.Show()

class aoOptions:
	def __init__(self, samples=3.0, maxDist=7.74, rayBias=0.2064, strength=1.0):
		self.dlg = PzrDialog(width=240, height=320)
		self.samplesBtn = Float6Button("aoSamples", text=samples, message="Samples", value=samples, command=10002)
		self.maxdistBtn = Float6Button("aoMaxDist", text=maxDist, message="MaxDist", value=maxDist, command=10003)
		self.raybiasBtn = Float6Button("aoRayBias", text=rayBias, message="RayBias", value=rayBias, command=10004)
		self.strengthBtn = Float6Button("aoStrength", text=strength, message="Strength", value=strength, command=10005)

		bigtext = PzrText(size=18)
		headline = PzrText(size=16)
		biline = PzrText(size=14, italic=1)

		self.dlg.add( PzrMessage("Ambient Occlusion", text=bigtext), 44, 34 )

		self.dlg.add( PzrMessage("Samples",text=headline), 24, 70 )
		self.dlg.add( PzrMessage("Smoothness of dark area.",text=biline), 24, 90 )
		self.dlg.add( self.samplesBtn, 124, 70 )

		self.dlg.add( PzrMessage("MaxDist",text=headline), 24, 120 )
		self.dlg.add( PzrMessage("Size of dark area.",text=biline), 24, 140 )
		self.dlg.add( self.maxdistBtn, 124, 120 )

		self.dlg.add( PzrMessage("RayBias",text=headline), 24, 170 )
		self.dlg.add( PzrMessage("Offset starting point of rays.",text=biline), 24, 190 )
		self.dlg.add( self.raybiasBtn, 124, 170 )

		self.dlg.add( PzrMessage("Strength",text=headline), 24, 220 )
		self.dlg.add( PzrMessage("Opacity of dark area.",text=biline), 24, 240 )
		self.dlg.add( self.strengthBtn, 124, 220 )

		self.dlg.add( PzrOkButton(), 164, 294)
		#self.dlg.add( PzrCancelButton(), 94, 294)
	def get(self):
		return gwrPass.occlusionOptions(samples=self.samplesBtn.get(), maxDist=self.maxdistBtn.get(), rayBias=self.raybiasBtn.get(), strength=self.strengthBtn.get())
	def Show(self):
		if self.dlg.Show():
			return self.get()
		else:
			return gwrPass.occlusionOptions()

class p4OptionsWindow:
	def __init__(self):
		bigtext = PzrText(size=18)
		self.dlg = PzrDialog(width=240,height=320)
		self.dlg.add( PzrMessage("Render Options", text=bigtext), 58, 34 )

		self.types = ["Use document settings.","Use these settings:"]
		self.typs = PzrRadioPane(initCommand=10101)
		for typ in self.types:
			self.typs.AddRadiobutton(typ)
		self.dlg.add( self.typs, 24, 64 )

		self.opts = PzrCheckPane(initCommand=10201)
		self.optionLabels = ['Anti-alias','Use bump maps','Use texture maps','Cast shadows']
		for opt in self.optionLabels:
			self.opts.AddCheckbutton(opt)
		self.dlg.add( self.opts, 48, 104 )

		self.dlg.add( PzrOkButton(), 164, 294)
	def get(self):
		eng = gwrRender.poser4()
		usedoc = not self.types.index(self.typs.get())
		if usedoc:
			return gwrRender.renderSettings(eng)
		else:
			useopts = self.opts.get()
			eng.setFlag("antialiasing", self.optionLabels[0] in useopts )
			eng.setFlag("useTexture", self.optionLabels[2] in useopts )
			eng.setFlag("useBump", self.optionLabels[1] in useopts )
			eng.setFlag("castShadows", self.optionLabels[3] in useopts )
			return gwrRender.renderSettings(eng)
	def Show(self):
		return self.dlg.Show()

class ffOptionsWindow:
	def __init__(self):
		bigtext = PzrText(size=18)
		self.dlg = PzrDialog(width=240,height=320)
		self.dlg.add( PzrMessage("Render Options", text=bigtext), 58, 34 )

		self.types = ["Use document settings.", "Use these settings:"]
		self.typs = PzrRadioPane(initCommand=10101)
		for typ in self.types:
			self.typs.AddRadiobutton(typ)
		self.dlg.add( self.typs, 24, 64 )

		self.loader = SelectPRPButton("prpButton")
		self.dlg.add( self.loader, 24, 104 )

		self.dlg.add( PzrOkButton(), 164, 294)
	def get(self):
		eng = gwrRender.fireFly()
		if self.types.index(self.typs.get()):
			prp = self.loader.get()
			if os.path.exists(prp):
				eng.load(self.loader.get())
		return gwrRender.renderSettings(eng)
	def Show(self):
		return self.dlg.Show()

class skOptionsWindow:
	def __init__(self):
		bigtext = PzrText(size=18)
		self.dlg = PzrDialog(width=240,height=320)
		self.dlg.add( PzrMessage("Sketch Options", text=bigtext), 58, 34 )

		self.types = ["Use document settings.", "Use these settings:"]
		self.typs = PzrRadioPane(initCommand=10101)
		for typ in self.types:
			self.typs.AddRadiobutton(typ)
		self.dlg.add( self.typs, 24, 64 )

		self.loader = SelectPZSButton("pzsButton")
		self.dlg.add( self.loader, 24, 104 )

		self.dlg.add( PzrOkButton(), 164, 294)
	def get(self):
		eng = gwrRender.poserSketch()
		if self.types.index(self.typs.get()):
			pzs = self.loader.get()
			if os.path.exists(pzs):
				eng.load(self.loader.get())
		return gwrRender.renderSettings(eng)
	def Show(self):
		return self.dlg.Show()

class pvOptionsWindow:
	def __init__(self):
		bigtext = PzrText(size=18)
		self.dlg = PzrDialog(width=240,height=320)
		self.dlg.add( PzrMessage("Preview Options", text=bigtext), 58, 34 )

		self.types = ["Use document settings.", "Use these settings:"]
		self.typs = PzrRadioPane(initCommand=10101)
		for typ in self.types:
			self.typs.AddRadiobutton(typ)
		self.dlg.add( self.typs, 24, 64 )

		self.opts = PzrCheckPane(initCommand=10201)
		self.optionLabels = ['Anti-alias']
		for opt in self.optionLabels:
			self.opts.AddCheckbutton(opt)
		self.dlg.add( self.opts, 48, 104 )

		self.dlg.add( PzrOkButton(), 164, 294)
	def get(self):
		eng = gwrRender.poserPreview()
		usedoc = not self.types.index(self.typs.get())
		if usedoc:
			return gwrRender.renderSettings(eng)
		else:
			useopts = self.opts.get()
			if self.optionLabels[0] in useopts:
				flag = "true"
			else:
				flag = "false"
			eng.setFlag("antiAlias", flag )
			rs = gwrRender.renderSettings(eng, movie=eng)
			rs.genFlag('useRenderer','preview')
			return rs
	def Show(self):
		return self.dlg.Show()

class gwrSettingsWindow:
	def __init__(self):
		bigtext = PzrText(size=18)
		self.dlg = PzrDialog(width=320,height=240)
		self.dlg.add( PzrMessage("Settings", text=bigtext), 124, 42 )

		se = getSettings()
		if GLOWWORM_PLATFORM == "mac":
			vm = [ se[PREF_DOLOG], se[PREF_WARNIF], se[PREF_RUNSIMS] ]
		else:
			vm = [ se[PREF_DOLOG], se[PREF_SHOWLOG], se[PREF_WARNIF], se[PREF_RUNSIMS] ]
		self.opts = PzrCheckPane(initCommand=10201, valueMap=vm)
		self.optioncodes = [PREF_DOLOG,PREF_SHOWLOG,PREF_WARNIF,PREF_RUNSIMS]
		self.optionLabels = [TEXT_DOLOG, TEXT_SHOWLOG, TEXT_WARNIF, TEXT_RUNSIMS]
		win_only = [ TEXT_SHOWLOG ]
		for opt in self.optionLabels:
			if opt in win_only and GLOWWORM_PLATFORM == "mac":
				continue
			else:
				self.opts.AddCheckbutton(opt)
		self.dlg.add( self.opts, 48, 86 )

		self.dlg.add( PzrOkButton(), 244, 214)
	def getKey(self, label):
		return self.optioncodes[ self.optionLabels.index(label) ]
	def get(self):
		doOpts = getSettings()
		for k in self.opts.get():
			doOpts[ self.getKey(k) ] = 1
		for k in self.optionLabels:
			if k not in self.opts.get():
				doOpts[ self.getKey(k) ] = 0
		return doOpts
	def Show(self):
		if self.dlg.Show():
			settingsOpts = self.get()
			for k, v in settingsOpts.items():
				setPref(k, v)

def AskRenderPass():
	rpm = renderPassMaker()
	if rpm.Show():
		return rpm.get()
	else:
		return None

def TestRenderPass():
	rp = AskRenderPass()
	if rp:
		scene = poser.Scene()
		rp.apply(scene)
		scene.Render()

def AskOptions(engine="ff"):
	if engine == "ff":
		win = ffOptionsWindow()
	elif engine == "p4":
		win = p4OptionsWindow()
	elif engine == "sk":
		win = skOptionsWindow()
	elif engine == "pv":
		win = pvOptionsWindow()
	else:
		return ErrorBox("No render engine specified.")
	if win.Show():
		return win.get()
	else:
		return None

class JobWidget:
	def __init__(self, widgetName, owner=None, command=10010):
		self.job = None
		self.jobFile = None
		self.owner = owner
		self.widgetName = widgetName
		self.wname = PzrMessage(widgetName + "Name", text=jobFont)
		self.wout = PzrMessage(widgetName + "Outdir", text=jobFont)
		self.wres = PzrMessage(widgetName + "Resolution", text=jobFont)
		self.wformat = PzrMessage(widgetName + "Format", text=jobFont)
		self.wframes = PzrMessage(widgetName + "Frames", text=jobFont)
		self.wpasses = PzrMessage(widgetName + "Passes", text=jobFont)
		self.wstatus = PzrMessage(widgetName + "Status", text=jobFont)
		self.werror = PzrMessage(widgetName + "Error", text=jobFont)
		self.btnCancel = PzrImageButton(widgetName + "Cancel", callback=self.Cancel, command=command, pictRes=14002, hiliteRes=14003, width=19, height=15)
		#self.btnOptions = PzrImageButton(widgetName + "Options", callback=self.Options, command=command+1, pictRes=14004, hiliteRes=14005, width=19, height=15)
	def place(self, x, y):
		xml = self.wname.place(x,y)
		xml = xml + self.wout.place(x+128, y)
		xml = xml + self.wformat.place(x+250,y)
		xml = xml + self.wframes.place(x+264,y)
		xml = xml + self.wres.place(x+332,y)
		xml = xml + self.wpasses.place(x+402,y)
		xml = xml + self.wstatus.place(x+584,y)
		xml = xml + self.werror.place(x+584,y)
		#xml = xml + self.btnCancel.place(x+716,y)
		#xml = xml + self.btnOptions.place(x+740,y)
		xml = xml + self.btnCancel.place(x+740,y)
		return xml
	def set(self, jobFile):
		self.jobFile = jobFile
		self.job = gwrParse.readJob(jobFile)
		self.SetText(file=self.job.getSource(), outdir=self.job.getOutdir(), format=self.job.getFormat(), res=self.job.getRes(), frames=self.job.getFrames(), passes=self.job.getPasses(), status=self.job.getStatus())
	def clear(self):
		self.SetText()
	def clearJob(self):
		self.job = None
		self.jobFile = None
	def Options(self, event=None):
		# Save log or not
		pass
	def Cancel(self, event=None):
		if not self.jobFile: return None
		if os.path.exists(self.jobFile):
			try:
				if os.path.exists(self.jobFile): os.remove(self.jobFile)
			except:
				ErrorBox("Problem deleting file: Please close Poser and try again.")
		self.job = None
		self.jobFile = None
		self.clear()
	def SetText(self, file="", outdir="", format="", res="", frames="", passes="", status="", error=0):
		self.SetFile(file)
		self.SetOutdir(outdir)
		self.SetFormat(format)
		self.SetRes(res)
		self.SetFrames(frames)
		self.SetPasses(passes)
		self.SetStatus(status, error=error)
	def SetFile(self, file):
		self.wname.SetText(self.dlg, file)
	def SetOutdir(self, outdir):
		if outdir:
			input = self.job.getSource()
			if os.path.splitext(input)[1]:
				outdir = os.path.splitext(input)[0]
			else:
				outdir = "fileName"
			outdir = outdir + ".@.#." + self.job.getFormat()
		self.wout.SetText(self.dlg, outdir)
	def SetFormat(self, format):
		#self.wformat.SetText(self.dlg, format)
		self.wformat.SetText(self.dlg,"")
	def SetRes(self, res):
		self.wres.SetText(self.dlg, res)
	def SetFrames(self, frames):
		self.wframes.SetText(self.dlg, frames)
	def SetPasses(self, passes):
		if self.jobFile and not passes:
			if self.job.settings.engineType() == 0:
				self.wpasses.SetText(self.dlg, "FireFly Render")
			elif self.job.settings.engineType() == 1:
				self.wpasses.SetText(self.dlg, "Poser 4 Render")
			elif self.job.settings.engineType() == 2:
				self.wpasses.SetText(self.dlg, "Sketch Render")
			elif self.job.settings.engineType() == 3:
				self.wpasses.SetText(self.dlg, "Preview Render")
			else:
				self.wpasses.SetText(self.dlg, "Use Doc's Render Settings")
		else:
			self.wpasses.SetText(self.dlg, passes)
	def SetStatus(self, status, error=0):
		if error:
			self.wstatus.SetText(self.dlg, "")
			self.werror.SetText(self.dlg, status)
		else:
			self.wstatus.SetText(self.dlg, status)
			self.werror.SetText(self.dlg, "")
	def Refresh(self):
		if self.jobFile:
			self.set(self.jobFile)
		else:
			self.clear()
	def SetDialog(self, dialog):
		self.dlg = dialog
		self.Refresh()
		dialog.AddButtonCallback(self.btnCancel.widgetName, self.Cancel)
		#dialog.AddButtonCallback(self.btnOptions.widgetName, self.Options)

class SelectEngineButton(PzrMenuButton):
	defaultText = TEXT_USEDOC
	defaultValue = None
	renderSettings = gwrRender.genericRS
	defaultMessage = "Render using:"
	engines = ["FireFly", "Poser 4", "Sketch", "Preview"]
	def __init__(self, widgetName, parent=None, command=10002, groupID=4, message=None, options=None):
		self.btn = PzrButton(widgetName, command=command, groupID=groupID)
		self.widgetName = widgetName
		self.default = self.defaultValue
		if message: self.message = message
		else: self.message = self.defaultMessage
		if options: self.options = options
		else: self.options = self.defaultOptions
		self.title = self.FormatText(self.defaultText)
		self.value = self.defaultValue
		self.parent = parent
	def get(self):
		return self.renderSettings
	def OnClick(self, event=None):
		newValue = self.AskValue()
		if newValue != self.null:
			self.value = self.FormatValue(newValue)
			newRS = AskOptions(engine=self.value)
			if newRS:
				self.renderSettings = newRS
			else:
				self.renderSettings = {"ff":gwrRender.rsFireFly, "p4":gwrRender.rsPoser4, "sk":gwrRender.rsSketch, "pv":gwrRender.rsPreview, self.defaultValue:gwrRender.genericRS}[self.value]
			self.ChangeText( self.FormatText(newValue) )
		else:
			self.value = None
			self.ChangeText(TEXT_USEDOC)
		if self.parent: self.parent.useEngine = self.value
	def GetOptions(self):
		return self.engines
	def FormatValue(self, value):
		return {"FireFly":"ff", "Poser 4":"p4", "Sketch":"sk", "Preview":"pv", "ff":"ff","p4":"p4","sk":"sk","pv":"pv",self.defaultText:self.defaultValue,self.defaultValue:self.defaultText}[value]

def folderSlashFile(text):
	text = os.path.split(text)
	return os.path.split(text[0])[1] + "/" + text[1]

def folderSlash(text):
	return os.path.basename(text) + "/"

class SelectOutputDirButton(PzrDirButton):
	def FormatText(self, text):
		text = folderSlashFile(text)
		if len(text) > 45: return text[-45:]
		else: return text

class SelectFormatButton(PzrMenuButton):
	defaultText = "TIF"
	defaultValue = "TIF"
	defaultMessage = "Save files as..."
	def GetOptions(self):
		return ["TIF","BMP","JPG","PCT","PNG"]

class SelectResButton(PzrValueButton):
	defaultText = TEXT_USEDOC
	defaultValue = (VAR_USEDOC,VAR_USEDOC)
	def AskValue(self):
		w = poser.DialogSimple.AskInt("Image width:")
		if w:
			h = poser.DialogSimple.AskInt("Image height:")
			if h:
				return (w,h)
		return self.null
	def FormatText(self, text):
		if text == self.null:
			return self.defaultText
		elif text == self.defaultText:
			return self.defaultText
		elif type(text) == type(""):
			return text
		else:
			return "%ix%i" % (text[0],text[1])
	def FormatValue(self, value):
		if value == self.null:
			return self.defaultValue
		else:
			return value

class SelectFramesButton(PzrValueButton):
	defaultText = TEXT_CURRENT #TEXT_USEDOC
	defaultValue = VAR_CURRENT #VAR_USEDOC
	def AskValue(self):
		v = AskMenu(message="Render frames:", options=[TEXT_CURRENT,TEXT_FRAMES,TEXT_USEDOC])
		if v == TEXT_FRAMES:
			s = poser.DialogSimple.AskInt("Start frame:")
			if s:
				e = poser.DialogSimple.AskInt("End frame:")
				if e:
					return "%i-%i" % (s, e)
		elif v:
			return v
		else:
			return TEXT_USEDOC
		return self.null
	def FormatText(self, text):
		if text == self.null:
			return TEXT_USEDOC
		else:
			return text
	def FormatValue(self, value):
		if value == self.null or value == TEXT_USEDOC:
			return VAR_USEDOC
		elif value == TEXT_CURRENT:
			return VAR_CURRENT
		elif value == self.defaultText:
			return VAR_USEDOC
		else:
			return tuple(value.split("-"))

class SelectRenderSettingsButton(PzrValueButton):
	defaultText = TEXT_USEDOC
	defaultValue = None
	def __init__(self, widgetName, parent=None, command=10002, groupID=4):
		self.null = "!NULL"
		self.parent = parent
		self.btn = PzrButton(widgetName, command=command, groupID=groupID)
		self.widgetName = widgetName
		self.default = self.defaultValue
		self.title = self.FormatText(self.defaultText)
		self.value = self.defaultValue
	def AskValue(self):
		return AskOptions(engine=self.parent.useEngine)
	def FormatText(self, text):
		if text and text != TEXT_USEDOC: return "Custom"
		else: return TEXT_USEDOC
	def FormatValue(self, value):
		if value: return value
		else: return None

def cleanSpecialChars(input):
	return re.sub("""\&""","+",input)

class JobMaker:
	def __init__(self, renderSceneFile=0, useFile=1, jobfile=None):
		self.useFile = useFile
		self.renderSceneFile = renderSceneFile
		self.warnWrongEngine = getSettings()["warnIf"]
		self.useEngine = None
		self.renderPasses = {}
		if renderSceneFile:
			self.src = os.path.abspath(self.renderSceneFile)
		self.jobfile = jobfile
	def GetDefaultRenderDir(self):
		if self.useFile:
			return os.path.join(os.path.dirname(self.src), "Renders")
		else:
			return os.path.join(os.path.normpath(self.src), "Renders")
	def BuildDialog(self):
		self.dlg = PzrDialog(width=480,height=320)
		self.dlg.add( PzrMessage("Render Job Options", text=PzrText(size=18)), 170, 34 )
		x1, x2, y = 32, 128, 64
		if self.useFile:
			sourceFormat = folderSlashFile(self.src)
		else:
			sourceFormat = folderSlash(self.src)
		sourceFormat = cleanSpecialChars(sourceFormat)
		self.selOutdir = SelectOutputDirButton("OutputButton", command=10901)
		self.selEngine = SelectEngineButton("RenderEngineButton", parent=self, command=10902)
		self.selSettings = SelectRenderSettingsButton("RenderSettingsButton", parent=self, command=10909)
		self.selFormat = SelectFormatButton("FormatButton", command=10903)
		self.selRes = SelectResButton("ResButton", command=10904)
		self.selFrames = SelectFramesButton("FramesButton", command=10905)
		self.renderPassesLabel = PzrMessage("Normal render.")
		outdir = self.GetDefaultRenderDir()
		self.selOutdir.set(outdir, outdir)
		self.dlg.add( PzrMessage("Render from:"), x1, y)
		self.dlg.add( PzrMessage(sourceFormat), x2, y)
		y = y + 30
		self.dlg.add( PzrMessage("Save renders to:"), x1, y)
		self.dlg.add( self.selOutdir, x2, y)
		y = y + 30
		self.dlg.add( PzrMessage("Render engine:"), x1, y)
		self.dlg.add( self.selEngine, x2, y)
		y = y + 30
		#self.dlg.add( PzrMessage("Render settings:"), x1, y)
		#self.dlg.add( self.selSettings, x2, y)
		#y = y + 30
		self.dlg.add( PzrMessage("Output format:"), x1, y)
		self.dlg.add( self.selFormat, x2, y)
		y = y + 30
		self.dlg.add( PzrMessage("Output size:"), x1, y)
		self.dlg.add( self.selRes, x2, y)
		y = y + 30
		self.dlg.add( PzrMessage("Output frames:"), x1, y)
		self.dlg.add( self.selFrames, x2, y)
		y = y + 30
		self.dlg.add( PzrMessage("Render passes:"), x1, y)
		self.dlg.add( self.renderPassesLabel, x2, y)
		self.dlg.add( PzrButton("Add", callback=self.AddRenderPass, command=10906), x2, y+20)
		self.dlg.add( PzrButton("Remove", callback=self.RemoveRenderPass, command=10907), x2+64, y+20)
		self.dlg.add( PzrButton("Remove All", callback=self.RemoveAllRenderPass, command=10908), x2+156, y+20)

		self.dlg.add( PzrCancelButton(), 340, 294)
		self.dlg.add( PzrOkButton(), 410, 294)
	def WarnRenderPass(self):
		return poser.DialogSimple.YesNo("Using render passes will cause the scene to be rendered with FireFly. Are you sure that you want to continue?")
	def AddRenderPass(self, event=None):
		wrp = 1
		if self.selEngine.get().engineType() != 0:
			if self.warnWrongEngine:
				wrp = self.WarnRenderPass()
		if wrp:
			rp = AskRenderPass()
			if rp:
				self.renderPasses[rp.id] = rp
				self.RedrawRPs()
	def RemoveRenderPass(self, event=None):
		ks = self.renderPasses.keys()
		ks.sort()
		delKey = AskMenu(message="Remove:", options=ks)
		if delKey:
			del self.renderPasses[delKey]
			self.RedrawRPs()
	def RemoveAllRenderPass(self, event=None):
		for k in self.renderPasses.keys():
			del self.renderPasses[k]
		self.RedrawRPs()
	def RedrawRPs(self):
		ks = self.renderPasses.keys()
		ks.sort()
		if len(ks) == 0: s = "Normal render."
		elif len(ks) == 1: s = ks[0]
		else:
			s = ks[0]
			for k in ks[1:]: s = s + ", " + k
		self.renderPassesLabel.SetText(self.dlg, s)
	def AskSource(self, useFile):
		if useFile:
			self.src = self.AskFile()
		else:
			self.src = self.AskFolder()
		return self.src
	def AskFile(self):
		fi = AskOpen(extensions=(".pz3",".pzz"), title="Select scene file...", dir=getPref(PREF_ADDFILE))
		if fi:
			setPref( 'addFile', os.path.dirname(fi) )
		return fi
	def AskFolder(self):
		fi = AskDirectory(title="Select a directory of Poser scenes to render.", dir=getPref(PREF_ADDFILE))
		if fi:
			setPref( 'addFile', fi )
		return fi
	def Format(self):
		return self.selFormat.get()
	def OutDir(self):
		return self.selOutdir.get()
	def Settings(self):
		return self.selSettings.get()
	def Engine(self):
		return self.selEngine.get()
	def Resolution(self):
		return self.selRes.get()
	def Height(self):
		return self.selRes.get()[1]
	def Width(self):
		return self.selRes.get()[0]
	def Frames(self):
		range = self.selFrames.get()
		if len(range) == 2:
			range = ( int(range[0]), int(range[1]) )
		else:
			pass
		return range
	def createRenderSettings(self):
		if self.Engine(): return gwrRender.renderSettings(self.Engine())
		else: return None
	def ShowEditMode(self, sourcejob=None):
		self.BuildDialog()
		if self.dlg.Show():
			gwrJob.createJob(jobfile=self.jobfile, srcpath=self.src, outdir=self.OutDir(), format=self.Format(), range=self.Frames(), width=self.Width(), height=self.Height(), settings=self.Engine(), passes=self.renderPasses.values())
			return 1
		else:
			return 0
	def Show(self):
		if self.renderSceneFile:
			self.BuildDialog()
			if self.dlg.Show():
				return gwrJob.renderJob(srcpath=self.renderSceneFile, outdir=self.OutDir(), format=self.Format(), range=self.Frames(), height=self.Height(), width=self.Width(), settings=self.Engine(), passes=self.renderPasses.values())
		elif self.AskSource(self.useFile):
			self.BuildDialog()
			if self.dlg.Show():
				gwrJob.createJob(jobfile=self.jobfile, srcpath=self.src, outdir=self.OutDir(), format=self.Format(), range=self.Frames(), width=self.Width(), height=self.Height(), settings=self.Engine(), passes=self.renderPasses.values())
				return 1
			else:
				return None
		else:
			return None
	def getJob(self):
		return gwrJob.renderJob(srcpath=self.renderSceneFile, outdir=self.OutDir(), format=self.Format(), range=self.Frames(), height=self.Height(), width=self.Width(), settings=self.Engine(), passes=self.renderPasses.values())

class GlowWorm:
	def __init__(self):
		settings = getSettings()
		self.doLog = settings[PREF_DOLOG]
		self.showLog = settings[PREF_SHOWLOG]
		self.warnRP = settings[PREF_WARNIF]
		self.alreadyAsked = 0
		self.dlg = PzrDialog(width=800,height=600,palettes="./runtime/Python/PoseWorks/GlowWorm/Data/14000.psd")
		y = 6
		self.dlg.add( PzrImage("bg",pictRes=14001, height=600, width=800), 0,0)
		self.dlg.add( PzrImageButton("addFile", callback=self.AddFile, command=10801, pictRes=14010, hiliteRes=14011, height=73, width=60), 341, y)
		self.dlg.add( PzrImageButton("addDir", callback=self.AddFolder, command=10802, pictRes=14020, hiliteRes=14021, height=73, width=68), 416, y)
		self.dlg.add( PzrImageButton("settings", callback=self.Settings, command=10803, pictRes=14030, hiliteRes=14031, height=73, width=60), 491+4, y)
		self.dlg.add( PzrImageButton("cancel", callback=self.CancelAll, command=10804, pictRes=14040, hiliteRes=14041, height=73, width=65), 566+4, y)
		self.dlg.add( PzrImageButton("render", callback=self.Render, command=10805, pictRes=14050, hiliteRes=14051, height=72, width=60), 641+6, y+1)
		self.dlg.add( PzrImageButton("close", command=7002, pictRes=14060, hiliteRes=14061, height=73, width=60), 716+6, y)

		#self.dlg.add( PzrImageButton("numbers", pictRes=14006, hiliteRes=14006, height=465, width=25), 13, 92)
		self.wJobs = []
		y = 96
		for i in range(16):
			self.wJobs.append( JobWidget("job%i" % i, command=10010+i*10) )
			self.dlg.add( self.wJobs[i], 24, y + 30*i)

		self.ProgressWidget = PzrMessage("Waiting for command.", text=liteFont)
		self.dlg.add( self.ProgressWidget, 560, 576 )
		#self.dlg.add( PzrMessage(GLOWWORM_VERSION, text=versFont), 246, 62 )
		self.dlg.add( PzrMessage(GLOWWORM_VERSION, text=versFont), 20, 576 )
		self.RedrawWidget = PzrMessage("Redraw")
		self.dlg.add(self.RedrawWidget, 900, 900)
		self.dlg.add( PzrImageButton("ImmediateStop", callback=self.ImmediateStop, command=10806, pictRes=14100, hiliteRes=14101, height=21, width=23), 770, 574)
	def GetDialog(self):
		return self.dlg.dlg
	def AddFile(self, event=None):
		JobMaker(useFile=1).Show()
		self.Refresh()
	def AddFolder(self, event=None):
		JobMaker(useFile=0).Show()
		self.Refresh()
	def Settings(self, event=None):
		gwrSettingsWindow().Show()
	def CancelAll(self, event=None):
		if poser.DialogSimple.YesNo("Remove all queued jobs?"):
			for job in os.listdir(gwrJob.renderJobsDir):
				os.remove( os.path.join(gwrJob.renderJobsDir, job) )
			self.Refresh()
	def ImmediateStop(self, event=None):
		if self.alreadyAsked:
			return None
		if not hasattr(self, "jobMan"):
			return ErrorBox("No renders in progress.")
		if poser.DialogSimple.YesNo("Stop rendering?"):
			self.alreadyAsked = 1
			self.jobMan.ABORT()
		else:
			self.alreadyAsked = 0
	def KillJob(self, jobIndex):
		os.remove(self.wJobs[jobIndex].jobFile)
	def FinishJob(self, event=None):
		self.wJobs[self.jobIndex].SetStatus("Done.")
		self.ProgressWidget.SetText(self.dlg, "Waiting for command.")
		self.KillJob(self.jobIndex)
		self.jobIndex = self.jobIndex + 1
	def CollectJobs(self):
		jobs = []
		for wJob in self.wJobs:
			if wJob.job:
				jobs.append(wJob.job)
		return jobs
	def Render(self, event=None):
		self.alreadyAsked = 0
		if self.doLog: self.log = renderLog()
		if askRenderAll():
                        if float(poser.Version()) >= 7:
                                if poser.DialogSimple.YesNo("Poser may close unexpectedly after the render is done, and you close the GlowWorm window.\n\nDo you want to continue?"):
                                        pass
                                else:
                                        raise gwrJob.excCancelRender
			self.Log("Render ordered by user.")
			self.Log("Collecting jobs...")
			renderTheseJobs = self.CollectJobs()
			if renderTheseJobs == []:
				return ErrorBox("No jobs to render.")
			self.Refresh()
			self.jobIndex = 0
			self.jobMan = gwrJob.jobManager( renderTheseJobs, runSims=getSettings()["runSims"] )
			self.jobMan.updateStatus = lambda v=None, s=self: s.DrawStatus(v)
			self.jobMan.finishJob = lambda v=None, s=self: s.FinishJob(v)
			#self.jobMan.updateCheck = lambda v=None, s=self: s.Draw(v)
			#--
			self.jobMan.renderAll()
			self.Log("Rendering complete.")
			if getPref(PREF_SHOWLOG):
                                        self.ShowLog()
			doShutdown()
			doClose()
			#--
			"""
			try:
				self.jobMan.renderAll()
				self.Log("Rendering complete.")
				if getPref(PREF_SHOWLOG):
                                        self.ShowLog()
				doShutdown()
				doClose()
			except gwrJob.excCancelRender:
				self.Log("Render canceled by user")
				self.UpdateStatus()
			except:
				info = sys.exc_info()
				ErrorBox("A error has occured, please close GlowWorm.")
				import traceback
				error = "An error occured while rendering:\n\n" + string.join( traceback.format_tb(info[2]) )
				error = error + "\nException Type: %s\n" % sys.exc_type
				error = error + "GlowWorm version: %s\n" % GLOWWORM_VERSION
				error = error + "Operating system: %s\n" % GLOWWORM_PLATFORM
				error = error + "Poser version: %s\n" % poser.Version()
				self.Log(error)
				print error
				print "Please report the entire text of this error to http://poseworks.com/smf/ (you can copy and paste.)"
				raise
			"""
			poser.NewDocument()
		else:
			self.Refresh()
		self.jobIndex = 0
		self.alreadyAsked = 0
	def UpdateStatus(self):
		self.ProgressWidget.SetText(self.dlg, self.jobMan.status)
		self.Log(self.jobMan.status)
	def DrawStatus(self, event=None):
		self.wJobs[self.jobIndex].SetStatus(self.DrawProgress())
		self.UpdateStatus()
	def Draw(self, event=None):
		self.RedrawWidget.SetText(self.dlg, "Redrawing")
	def DrawProgress(self):
		perc = repr(self.jobMan.percentDone)
		if len(perc) > 5:
			perc = perc[:5]
		perc = "Rendering... " + perc + "%"
		return perc
	def AssignJobsToButtons(self):
		for widget in self.wJobs:
			widget.clearJob()
		gw6s = gwrJob.getJobs()
		for gw6 in gw6s:
			i = gw6s.index(gw6)
			self.wJobs[i].jobFile = gw6
			if i == 15: return 1
	def Refresh(self):
		self.AssignJobsToButtons()
		for widget in self.wJobs: widget.Refresh()
	def Show(self):
		if isCompatiblePoser():
			self.AssignJobsToButtons()
			return self.dlg.Show()
		else:
			return 0
	def Log(self, text):
		if hasattr(self, "log"): self.log.add(text)
	def ShowLog(self):
		try: os.startfile(self.log.file)
		except: MessageBox("Rendering complete.")

def RenderCurrentScene():
	tempfile = "tempSource.pz3"
	jm = JobMaker(renderSceneFile=tempfile,useFile=1)
	job = jm.Show()
	if job:
		poser.SaveDocument("temp.pz3")
		jobMan = gwrJob.jobManager([], runSims=getPref(PREF_RUNSIMS) )
		jobMan.renderFile(tempfile, job)
	else:
		return 0
	return 1

def CleanUp():
	os.chdir( os.path.dirname(poser.AppLocation()) )
	for file in ["Current.gw6","Last.gw6","gwrTemp.cm2","temp.lt2","temp.pz3","temp.pmd","tempDlg.xml"]:
		try:
			os.remove(file)
		except:
			continue
	for file in os.listdir(os.getcwd()):
		if file[-3:].lower() == "dyn":
			os.remove(file)

if __name__ == '__main__':
	#TestRenderPass()
	AskRenderPass()

	#AskOptions(engine="ff")
	#AskOptions(engine="p4")
	#AskOptions(engine="sk")
	#AskOptions(engine="pv")

	#rs = gwrRender.renderSettings(gwrRender.poserPreview())
	#rs.movie = AskOptions(engine="pv")
	#rs.apply(poser.Scene())

	#gw = GlowWorm()
	#gw.Show()
	#CleanUp()

	#jm = JobMaker(useFile=0)
	#jm.Show()

	#askRenderAll()

pass
